﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spanner;

namespace SpannerWebSite
{
    internal partial class RefTypes : Reference
    {
        internal static SpannerChapter TheChapter;

        static RefTypes()
        {
            var sections = new List<SpannerSection> { };
            var initActs = new List<Act> { };

            Action<string, string, Html> addSection = (title, id, html) =>
            {
                sections.Add(Section(Esc(title), id, html));
            };

            addSection("Act type", "ActType", P("This type corresponds to JavaScript actions: ",
                "code that is executed for its side effects, but which has no value as an expression."));

            addSection("Expr<T> type", "ExprType", P("This type corresponds to JavaScript expressions ",
                "(values) of the given type."));

            addSection("Var<T> type", "VarType", P("This type corresponds to ordinary (unobservable) ",
                "JavaScript variables.  This is a subtype of ", Code("Expr<T>"), "."));

            addSection("ObsVar<T> type", "ObsVarType", P("This type corresponds to ", Knockout, " ",
                "observable variables.  Obsvars are transparently dereferenced in expressions and ",
                "assignments to obsvars are handled correctly.  This is a subtype of ", Code("Expr<T>"), "."));

            addSection("ObsVarRef<T> type", "ObsVarRefType", P("This type corresponds to ", Knockout, " ",
                "observable variable references: obsvarrefs are not transparently dereferenced in ",
                "expressions.  This allows one to write code which refers to an obsvar in itself, ",
                "as opposed to the value it carries.  An obsvarref for obsvar ", Code("x"), " ",
                "can be obtained via ", Code("Ref(x)"), "."));

            addSection("ComputedVar<T> type", "ComputedVarType", P("This type corresponds to ", Knockout, " ",
                "computed observables.  Computedvars are transparently dereferenced in expressions.  ",
                "This is a subtype of ", Code("Expr<T>"), "."));

            addSection("ComputedVarRef<T> type", "ComputedVarRefType", P("This type corresponds to ", Knockout, " ",
                "computed observable variable references: computedvarrefs are not transparently dereferenced in ",
                "expressions.  This allows one to write code which refers to an computedvar in itself, ",
                "as opposed to the value it carries.  A computedvarref for computedvar ", Code("x"), " ",
                "can be obtained via ", Code("Ref(x)"), "."));

            addSection("Param<T> type", "ParamType", P("This type corresponds to JavaScript function ",
                "parameters."));

            addSection("IndexExpr<T> type", "IndexExprType", P("This type corresponds to an element of an ",
                "array.  If ", Code("x"), " is an array, then ", Code("Ith(x, i)"), " is the indexexpr ",
                "denoting element ", Code("i"), " of ", Code("x"), "(that is, ", Code("x[i]"), ").  ",
                "Indexexprs can be ", Code("Set"), " ",
                "or treated as ", Code("Expr<T>"), " values.  ",
                "[The awkward syntax is the best one can do given C# as the host language.]"));

            addSection("FieldExpr<T> type", "FieldExprType", P("This type corresponds to a field of an ",
                "object.  If ", Code("x"), " is an object, then ", Code("Field(x, o => o.fld)"), " ",
                "is the fieldexpr denoting field ", Code("fld"), " of ", Code("x"), " (that is, ",
                Code("x.fld"), ").  ",
                "Fieldexprs can be ", Code("Set"), " or treated as ", Code("Expr<T>"), " values.  ",
                "[The awkward syntax is the best one can do given C# as the host language.]"));

            addSection("Other types", "xyz", P("Fill this in!").WithAttr("style", "color: red"));

            TheChapter = CommonUI.Chapter("Reference - Types", "RefTypes", sections, initActs);
        }
    }
}
